package com.my.lucky.util;

import com.my.lucky.model.Stock;

import java.util.ArrayList;
import java.util.List;

/**
 * BOLL指标计算器，专注于利用最近三天数据判断当日通道状态
 */
public class BollingerBandCalculator {

    static int days = 3;//计算的天数

    /**
     * 测试方法
     */
    public static void main(String[] args) {
        // 创建测试数据（前天、昨天、今天）
        List<Stock> threeDaysData = new ArrayList<>();

        // 测试场景1：通道扩张
//        threeDaysData.add(new Stock(110.0, 100.0, 90.0));   // 前天
//        threeDaysData.add(new Stock(112.0, 100.5, 89.0));  // 昨天
//        threeDaysData.add(new Stock(118.0, 101.0, 84.0));  // 今天 - 扩张
//
//        BollingerBandCalculator calculator = new BollingerBandCalculator();
//        BollingerAnalysisResult todayResult = calculator.judgeTodayStatus(threeDaysData);
////
//        System.out.println("测试场景1 - 通道扩张:");
//        System.out.println("今天的状态分析: " + todayResult);
//        System.out.println("变化描述: " + calculator.getTodayChangeDescription(todayResult) + "\n");
//
//        // 测试场景2：通道收缩
//        threeDaysData.clear();
//        threeDaysData.add(new Stock(115.0, 100.0, 85.0));   // 前天
//        threeDaysData.add(new Stock(112.0, 100.0, 88.0));  // 昨天
//        threeDaysData.add(new Stock(108.0, 100.0, 92.0));  // 今天 - 收缩
//
//        todayResult = calculator.judgeTodayStatus(threeDaysData);
//        System.out.println("测试场景2 - 通道收缩:");
//        System.out.println("今天的状态分析: " + todayResult);
//        System.out.println("变化描述: " + calculator.getTodayChangeDescription(todayResult) + "\n");
//
//        // 测试场景3：通道稳定
//        threeDaysData.clear();
//        threeDaysData.add(new Stock(110.0, 100.0, 90.0));   // 前天
//        threeDaysData.add(new Stock(111.0, 100.0, 89.0));  // 昨天
//        threeDaysData.add(new Stock(110.5, 100.0, 89.5));  // 今天 - 稳定

//        todayResult = calculator.judgeTodayStatus(threeDaysData);
        System.out.println("测试场景3 - 通道稳定:");
//        System.out.println("今天的状态分析: " + todayResult);
//        System.out.println("变化描述: " + calculator.getTodayChangeDescription(todayResult));
    }

    /**
     * 计算最近几天的通道状态，重点是最新一天
     */
//    private void calculateRecentStatus(List<BollingerAnalysisResult> results) {
//        if (results.size() == 1) {
//            // 只有今天的数据，无法比较
//            results.get(0).setBandStatus(BandStatus.UNKNOWN);
//            return;
//        }
//        // 计算每天的变化率
//        for (int i = 1; i < results.size(); i++) {
//            BollingerAnalysisResult current = results.get(i);
//            BollingerAnalysisResult previous = results.get(i - 1);
//            double changeRate = (current.getBandWidth() - previous.getBandWidth())
//                    / previous.getBandWidth() * 100;
//            current.setBandWidthChangeRate(changeRate);
//        }
//        // 对于有三天数据的情况，使用前两天的平均值作为参考
//        if (results.size() >= days) {
//            BollingerAnalysisResult today = results.get(0);
//            BollingerAnalysisResult yesterday = results.get(1);
//            BollingerAnalysisResult dayBeforeYesterday = results.get(2);
//            // 计算前两天的平均带宽
//            double twoDayAvg = (yesterday.getBandWidth() + dayBeforeYesterday.getBandWidth()) / 2;
//            // 计算前两天的带宽变化率作为参考阈值
//            double referenceChange = Math.abs(yesterday.getBandWidthChangeRate());
//            // 动态阈值：参考变化率的50%或5%中的较大值，避免极端情况
//            double threshold = Math.max(referenceChange * 0.5, 5.0);
//
//            // 判断今天的状态
//            if (today.getBandWidthChangeRate() > threshold) {
//                today.setBandStatus(BandStatus.EXPANDING);
//            } else if (today.getBandWidthChangeRate() < -threshold) {
//                today.setBandStatus(BandStatus.CONTRACTING);
//            } else {
//                today.setBandStatus(BandStatus.STABLE);
//            }
//        } else if (results.size() == 2) {
//            // 只有两天数据（昨天和今天）的情况
//            BollingerAnalysisResult today = results.get(1);
//            // 使用10%作为默认阈值
//            double threshold = 10.0;
//            if (today.getBandWidthChangeRate() > threshold) {
//                today.setBandStatus(BandStatus.EXPANDING);
//            } else if (today.getBandWidthChangeRate() < -threshold) {
//                today.setBandStatus(BandStatus.CONTRACTING);
//            } else {
//                today.setBandStatus(BandStatus.STABLE);
//            }
//        }
//    }

    /**
     * 判断今天的BOLL通道状态（基于今天、昨天数据）
     * @param threeDaysData 包含最近三天BOLL数据的列表，按时间顺序排列（昨天、今天）
     * @return 今天的通道状态分析结果
     */
    public BollingerAnalysisResult judgeTodayStatus(List<Stock> threeDaysData, double index) {
        // 验证输入数据
        if (threeDaysData == null || threeDaysData.size() < 1) {
            throw new IllegalArgumentException("至少需要一天的数据");
        }

        // 确保数据按时间排序（最早的在前，最新的在后）
        List<Stock> sortedData = new ArrayList<>(threeDaysData);

        // 计算每一天的带宽
        List<BollingerAnalysisResult> results = new ArrayList<>();
        for (Stock data : sortedData) {
            double bandWidth = (data.getBollUpper() - data.getBollLower()) / data.getBollMid();
            results.add(new BollingerAnalysisResult(
                    data.getBollUpper(),
                    data.getBollMid(),
                    data.getBollLower(),
                    bandWidth,
                    data.getClose()));
        }

        // 计算状态
        calculateRecentStatus(results, index);

        // 返回今天的状态（第一个元素）
        return results.get(0);
    }

    /**
     * 计算最近几天的通道状态，重点是最新一天
     */
    private void calculateRecentStatus(List<BollingerAnalysisResult> results, double index) {
        if (results.size() == 1) {
            // 只有今天的数据，无法比较
            results.get(0).setBandStatus(BandStatus.UNKNOWN);
            return;
        }
        // 计算每天的变化率
        for (int i = 1; i < results.size(); i++) {
            BollingerAnalysisResult current = results.get(i);
            BollingerAnalysisResult previous = results.get(i - 1);
            double changeRate = (current.getBandWidth() - previous.getBandWidth())
                    / previous.getBandWidth() * 100;
            current.setBandWidthChangeRate(changeRate);
        }
        // 对于有三天数据的情况，使用前两天的平均值作为参考
        if (results.size() >= 2) {
            BollingerAnalysisResult today = results.get(0);
            BollingerAnalysisResult yesterday = results.get(1);
//            BollingerAnalysisResult dayBeforeYesterday = results.get(2);
            // 计算前两天的平均带宽

            // 判断今天的状态
            double todayUpperLower = today.getUpperBand() - today.getLowerBand();
            double yesterdayUpperLower = yesterday.getUpperBand() - yesterday.getLowerBand();
            double twoDayAvgBand = (todayUpperLower - yesterdayUpperLower) / yesterdayUpperLower;

//            double dayBeforeYesterdayUpperLower = dayBeforeYesterday.getUpperBand() - dayBeforeYesterday.getLowerBand();
//            double twodayBeforeDayAvgBand = (yesterdayUpperLower - dayBeforeYesterdayUpperLower) / dayBeforeYesterdayUpperLower;

            //中线上升 开口加大，加大比例大于10% 下轨下跌 上轨向上
            if (today.getMiddleBand() > yesterday.getMiddleBand()  //中规向上
                    && todayUpperLower >= yesterdayUpperLower && twoDayAvgBand >= index //开口加大
                    && today.getLowerBand() < yesterday.getLowerBand() //下轨向下
                    && today.getUpperBand() > yesterday.getUpperBand() //上轨向上
                    && today.getPrice() > today.getMiddleBand() //价格大于中规

//                    && yesterday.getMiddleBand() > dayBeforeYesterday.getMiddleBand()  //中规向上
//                    && yesterdayUpperLower >= dayBeforeYesterdayUpperLower && twodayBeforeDayAvgBand >= index //开口加大
//                    && yesterday.getLowerBand() < dayBeforeYesterday.getLowerBand() //下轨向下
//                    && yesterday.getUpperBand() > dayBeforeYesterday.getUpperBand() //上轨向上

//                    && yesterday.getPrice() > yesterday.getMiddleBand() //价格大于中规

//                    && today.getPrice() < today.getUpperBand() //价格小于上轨
            ) {
                today.setBandStatus(BandStatus.EXPANDING);
//            } else if (today.getBandWidthChangeRate() < -threshold) {
//                today.setBandStatus(BandStatus.CONTRACTING);
//            } else {
//                today.setBandStatus(BandStatus.STABLE);
            }
//        } else if (results.size() == 2) {
//            // 只有两天数据（昨天和今天）的情况
//            BollingerAnalysisResult today = results.get(1);
//            // 使用10%作为默认阈值
//            double threshold = 10.0;
//            if (today.getBandWidthChangeRate() > threshold) {
//                today.setBandStatus(BandStatus.EXPANDING);
//            } else if (today.getBandWidthChangeRate() < -threshold) {
//                today.setBandStatus(BandStatus.CONTRACTING);
//            } else {
//                today.setBandStatus(BandStatus.STABLE);
//            }
        }
    }
    /**
     * 判断今天的BOLL通道状态（基于今天、昨天 前天数据）
     * @param threeDaysData 包含最近三天BOLL数据的列表，按时间顺序排列（前天 昨天、今天）
     * @return 今天的通道状态分析结果
     */
    public BollingerAnalysisResult judge3DStatus(List<Stock> threeDaysData, double index) {
        // 验证输入数据
        if (threeDaysData == null || threeDaysData.size() < 1) {
            throw new IllegalArgumentException("至少需要一天的数据");
        }

        // 确保数据按时间排序（最早的在前，最新的在后）
        List<Stock> sortedData = new ArrayList<>(threeDaysData);

        // 计算每一天的带宽
        List<BollingerAnalysisResult> results = new ArrayList<>();
        for (Stock data : sortedData) {
            double bandWidth = (data.getBollUpper() - data.getBollLower()) / data.getBollMid();
            results.add(new BollingerAnalysisResult(
                    data.getBollUpper(),
                    data.getBollMid(),
                    data.getBollLower(),
                    bandWidth,
                    data.getClose()));
        }

        // 计算状态
        calculateRecent3DStatus(results, index);

        // 返回今天的状态（第一个元素）
        return results.get(0);
    }

    /**
     * 计算最近几天的通道状态，重点是最新一天
     */
    private void calculateRecent3DStatus(List<BollingerAnalysisResult> results, double index) {
        if (results.size() == 1) {
            // 只有今天的数据，无法比较
            results.get(0).setBandStatus(BandStatus.UNKNOWN);
            return;
        }
        // 计算每天的变化率
        for (int i = 1; i < results.size(); i++) {
            BollingerAnalysisResult current = results.get(i);
            BollingerAnalysisResult previous = results.get(i - 1);
            double changeRate = (current.getBandWidth() - previous.getBandWidth())
                    / previous.getBandWidth() * 100;
            current.setBandWidthChangeRate(changeRate);
        }
        // 对于有三天数据的情况，使用前两天的平均值作为参考
        if (results.size() >= 2) {
            BollingerAnalysisResult today = results.get(0);
            BollingerAnalysisResult yesterday = results.get(1);
            BollingerAnalysisResult dayBeforeYesterday = results.get(2);
            // 计算前两天的平均带宽

            // 判断今天的状态
            double todayUpperLower = today.getUpperBand() - today.getLowerBand();
            double yesterdayUpperLower = yesterday.getUpperBand() - yesterday.getLowerBand();
            double twoDayAvgBand = (todayUpperLower - yesterdayUpperLower) / yesterdayUpperLower;

            double dayBeforeYesterdayUpperLower = dayBeforeYesterday.getUpperBand() - dayBeforeYesterday.getLowerBand();
            double twodayBeforeDayAvgBand = (yesterdayUpperLower - dayBeforeYesterdayUpperLower) / dayBeforeYesterdayUpperLower;

            //中线上升 开口加大，加大比例大于10% 下轨下跌 上轨向上
            if (today.getMiddleBand() > yesterday.getMiddleBand()  //中规向上
                    && todayUpperLower >= yesterdayUpperLower && twoDayAvgBand >= index //开口加大
                    && today.getLowerBand() < yesterday.getLowerBand() //下轨向下
                    && today.getUpperBand() > yesterday.getUpperBand() //上轨向上
                    && today.getPrice() > today.getMiddleBand() //价格大于中规

                    && yesterday.getMiddleBand() > dayBeforeYesterday.getMiddleBand()  //中规向上
                    && yesterdayUpperLower >= dayBeforeYesterdayUpperLower && twodayBeforeDayAvgBand >= index //开口加大
                    && yesterday.getLowerBand() < dayBeforeYesterday.getLowerBand() //下轨向下
                    && yesterday.getUpperBand() > dayBeforeYesterday.getUpperBand() //上轨向上

//                    && yesterday.getPrice() > yesterday.getMiddleBand() //价格大于中规

//                    && today.getPrice() < today.getUpperBand() //价格小于上轨
            ) {
                today.setBandStatus(BandStatus.EXPANDING);
//            } else if (today.getBandWidthChangeRate() < -threshold) {
//                today.setBandStatus(BandStatus.CONTRACTING);
//            } else {
//                today.setBandStatus(BandStatus.STABLE);
            }
//        } else if (results.size() == 2) {
//            // 只有两天数据（昨天和今天）的情况
//            BollingerAnalysisResult today = results.get(1);
//            // 使用10%作为默认阈值
//            double threshold = 10.0;
//            if (today.getBandWidthChangeRate() > threshold) {
//                today.setBandStatus(BandStatus.EXPANDING);
//            } else if (today.getBandWidthChangeRate() < -threshold) {
//                today.setBandStatus(BandStatus.CONTRACTING);
//            } else {
//                today.setBandStatus(BandStatus.STABLE);
//            }
        }
    }

    /**
     * 判断今天的BOLL通道状态（基于今天、昨天三天数据）
     *
     * @param threeDaysData 包含最近三天BOLL数据的列表，按时间顺序排列（昨天、今天）
     * @return 今天的通道状态分析结果
     */
    public BollingerAnalysisResult judgeTodayLimitStatus(List<Stock> threeDaysData, double index) {
        // 验证输入数据
        if (threeDaysData == null || threeDaysData.size() < 1) {
            throw new IllegalArgumentException("至少需要一天的数据");
        }

        // 确保数据按时间排序（最早的在前，最新的在后）
        List<Stock> sortedData = new ArrayList<>(threeDaysData);

        // 计算每一天的带宽
        List<BollingerAnalysisResult> results = new ArrayList<>();
        for (Stock data : sortedData) {
            double bandWidth = (data.getBollUpper() - data.getBollLower()) / data.getBollMid();
            results.add(new BollingerAnalysisResult(
                    data.getBollUpper(),
                    data.getBollMid(),
                    data.getBollLower(),
                    bandWidth,
                    data.getClose()));
        }

        // 计算状态
        calculateRecentLimitStatus(results, index);

        // 返回今天的状态（第一个元素）
        return results.get(0);
    }

    /**
     * 计算最近几天的通道状态，重点是最新一天
     * 涨停数据:
     */
    private void calculateRecentLimitStatus(List<BollingerAnalysisResult> results, double index) {
        if (results.size() == 1) {
            // 只有今天的数据，无法比较
            results.get(0).setBandStatus(BandStatus.UNKNOWN);
            return;
        }
        // 计算每天的变化率
        for (int i = 1; i < results.size(); i++) {
            BollingerAnalysisResult current = results.get(i);
            BollingerAnalysisResult previous = results.get(i - 1);
            double changeRate = (current.getBandWidth() - previous.getBandWidth())
                    / previous.getBandWidth() * 100;
            current.setBandWidthChangeRate(changeRate);
        }
        // 对于有三天数据的情况，使用前两天的平均值作为参考
        if (results.size() >= 3) {
            BollingerAnalysisResult today = results.get(0);
            BollingerAnalysisResult yesterday = results.get(1);
            BollingerAnalysisResult dayBeforeYesterday = results.get(2);
            // 计算前两天的平均带宽

            // 判断今天的状态
            double todayUpperLower = today.getUpperBand() - today.getLowerBand();
            double yesterdayUpperLower = yesterday.getUpperBand() - yesterday.getLowerBand();
            double twoDayAvgBand = (todayUpperLower - yesterdayUpperLower) / yesterdayUpperLower;
            double todaymidCha = yesterday.getMiddleBand()-today.getMiddleBand();
            double yesmidCha = dayBeforeYesterday.getMiddleBand()-yesterday.getMiddleBand();
            double dayBeforeYesterdayUpperLower = dayBeforeYesterday.getUpperBand() - dayBeforeYesterday.getLowerBand();
            double twodayBeforeDayAvgBand = (yesterdayUpperLower - dayBeforeYesterdayUpperLower) / dayBeforeYesterdayUpperLower;

            //中线上升 开口加大，加大比例大于10% 下轨下跌 上轨向上
            if ( (today.getMiddleBand() >= yesterday.getMiddleBand() ||  yesmidCha>todaymidCha)//中规向上
                    && todayUpperLower >= yesterdayUpperLower && twoDayAvgBand >= index //开口加大
//                    && today.getLowerBand() < yesterday.getLowerBand() //下轨向下
                    && today.getUpperBand() > yesterday.getUpperBand() //上轨向上

                    && today.getPrice() > today.getMiddleBand() //价格大于中规

//                    && yesterday.getMiddleBand() > dayBeforeYesterday.getMiddleBand()  //中规向上
//                    && yesterdayUpperLower >= dayBeforeYesterdayUpperLower && twodayBeforeDayAvgBand >= index //开口加大
//                    && yesterday.getLowerBand() < dayBeforeYesterday.getLowerBand() //下轨向下
//                    && yesterday.getUpperBand() > dayBeforeYesterday.getUpperBand() //上轨向上

//                    && yesterday.getPrice() > yesterday.getMiddleBand() //价格大于中规

//                    && today.getPrice() < today.getUpperBand() //价格小于上轨
            ) {
                today.setBandStatus(BandStatus.EXPANDING);
//            } else if (today.getBandWidthChangeRate() < -threshold) {
//                today.setBandStatus(BandStatus.CONTRACTING);
//            } else {
//                today.setBandStatus(BandStatus.STABLE);
            }
//        } else if (results.size() == 2) {
//            // 只有两天数据（昨天和今天）的情况
//            BollingerAnalysisResult today = results.get(1);
//            // 使用10%作为默认阈值
//            double threshold = 10.0;
//            if (today.getBandWidthChangeRate() > threshold) {
//                today.setBandStatus(BandStatus.EXPANDING);
//            } else if (today.getBandWidthChangeRate() < -threshold) {
//                today.setBandStatus(BandStatus.CONTRACTING);
//            } else {
//                today.setBandStatus(BandStatus.STABLE);
//            }
        }
    }

    /**
     * 获取今天相对于昨天的通道变化描述
     */
    public String getTodayChangeDescription(BollingerAnalysisResult todayResult) {
        if (todayResult == null) {
            return "无数据";
        }

        BandStatus status = todayResult.getBandStatus();
        double changeRate = todayResult.getBandWidthChangeRate();

        switch (status) {
            case EXPANDING:
                return String.format("通道扩张 (%.2f%%)：市场波动性增加", changeRate);
            case CONTRACTING:
                return String.format("通道收缩 (%.2f%%)：市场波动性降低", changeRate);
            case STABLE:
                return String.format("通道稳定 (%.2f%%)：市场波动性变化不大", changeRate);
            default:
                return "无法判断通道状态：数据不足";
        }
    }

    /**
     * 通道状态枚举（包含键值对形式的状态描述）
     */
    public enum BandStatus {
        EXPANDING("EXPANDING", "通道扩张"),   // 键：EXPANDING，值：通道扩张
        CONTRACTING("CONTRACTING", "通道收缩"), // 键：CONTRACTING，值：通道收缩
        STABLE("STABLE", "通道稳定"),         // 键：STABLE，值：通道稳定
        UNKNOWN("UNKNOWN", "未知状态");       // 键：UNKNOWN，值：未知状态

        // 枚举的键
        private final String key;
        // 枚举的值（描述信息）
        private final String value;

        // 构造方法，初始化键和值
        BandStatus(String key, String value) {
            this.key = key;
            this.value = value;
        }

        // 根据键获取对应的枚举实例
        public static BandStatus fromKey(String key) {
            for (BandStatus status : BandStatus.values()) {
                if (status.key.equals(key)) {
                    return status;
                }
            }
            return UNKNOWN; // 默认返回未知状态
        }

        // 根据值获取对应的枚举实例
        public static BandStatus fromValue(String value) {
            for (BandStatus status : BandStatus.values()) {
                if (status.value.equals(value)) {
                    return status;
                }
            }
            return UNKNOWN; // 默认返回未知状态
        }

        // 获取键
        public String getKey() {
            return key;
        }

        // 获取值
        public String getValue() {
            return value;
        }
    }

    /**
     * BOLL分析结果类
     */
    public static class BollingerAnalysisResult {
        private final double upperBand;
        private final double middleBand;
        private final double lowerBand;
        private final double bandWidth;
        private BandStatus bandStatus;
        private double bandWidthChangeRate;
        private final double price;

        public BollingerAnalysisResult(double upperBand, double middleBand, double lowerBand,
                                       double bandWidth, double price) {
            this.upperBand = upperBand;
            this.middleBand = middleBand;
            this.lowerBand = lowerBand;
            this.bandWidth = bandWidth;
            this.price = price;
            this.bandStatus = BandStatus.UNKNOWN;
            this.bandWidthChangeRate = 0.0;
        }

        // Getters
        public double getUpperBand() {
            return upperBand;
        }

        public double getMiddleBand() {
            return middleBand;
        }

        public double getLowerBand() {
            return lowerBand;
        }

        public double getBandWidth() {
            return bandWidth;
        }

        public BandStatus getBandStatus() {
            return bandStatus;
        }

        // Setters
        public void setBandStatus(BandStatus bandStatus) {
            this.bandStatus = bandStatus;
        }

        public double getBandWidthChangeRate() {
            return bandWidthChangeRate;
        }

        public void setBandWidthChangeRate(double rate) {
            this.bandWidthChangeRate = rate;
        }

        public double getPrice() {
            return price;
        }

        @Override
        public String toString() {
            return "BollingerAnalysisResult{" +
                    "upperBand=" + upperBand +
                    ", middleBand=" + middleBand +
                    ", lowerBand=" + lowerBand +
                    ", bandWidth=" + bandWidth +
                    ", bandStatus=" + bandStatus +
                    ", bandWidthChangeRate=" + bandWidthChangeRate +
                    ", price=" + price +
                    '}';
        }
    }
}
